package com.ctu.gzero.utils
{
	import com.ctu.gzero.compose.TxLine;
	import com.ctu.gzero.compose.TxLineSegment;
	import com.ctu.gzero.edit.SelectionState;
	import com.ctu.gzero.elements.DOMElement;
	import com.ctu.gzero.elements.ParaElement;
	
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.engine.TextLine;
	
	public class TextRangeUtil
	{
		public function TextRangeUtil()
		{
		}
		
		public static function previousCharacter(selectionState:SelectionState, extendSelection:Boolean):Boolean
		{
			var isChanged:Boolean;
			var dom:DOMElement = selectionState.dom;
			var anchorPosition:int = selectionState.anchorPosition;
			var activePosition:int = selectionState.activePosition;
			var endFlag:Boolean = selectionState.endFlag;
			var para:ParaElement;
			
			if(!extendSelection) // shift key is not pressed
			{
				if(anchorPosition != activePosition) // area selection
				{
					anchorPosition =  activePosition = Math.min(anchorPosition, activePosition);
				}
				else // caret selection
				{
					anchorPosition = activePosition = (anchorPosition -1 >= 0) ? anchorPosition -1 : 0;
					endFlag = false;
				}
				
			}
			else 
			{
				//TODO: implement
			}
			
			isChanged = checkChange(selectionState, anchorPosition, activePosition, endFlag);
			
			if(isChanged)
				selectionState.updateRange(anchorPosition, activePosition, endFlag);

			return isChanged;
		}
		
		public static function nextCharacter(selectionState:SelectionState, extendSelection:Boolean):Boolean
		{
			var isChanged:Boolean;
			var dom:DOMElement = selectionState.dom;
			var anchorPosition:int = selectionState.anchorPosition;
			var activePosition:int = selectionState.activePosition;
			var endFlag:Boolean = selectionState.endFlag;
			var para:ParaElement;
			
			if(!extendSelection) // shift key is not pressed
			{
				if(anchorPosition != activePosition) // area selection
				{
					anchorPosition =  activePosition = Math.max(anchorPosition, activePosition);
				}
				else // caret selection
				{
					anchorPosition = activePosition =  (anchorPosition + 1 <= dom.textLength -1) ? anchorPosition + 1 : dom.textLength -1;
					endFlag = false;
				}
			}
			else 
			{
				//TODO: implement
			}
			
			isChanged = checkChange(selectionState, anchorPosition, activePosition, endFlag);
			
			if(isChanged)
				selectionState.updateRange(anchorPosition, activePosition, endFlag);
				
			return isChanged;
		}
		
		public static function endOfLine(selectionState:SelectionState, extendSelection:Boolean):Boolean
		{
			var isChanged:Boolean;
			var dom:DOMElement = selectionState.dom;
			var anchorPosition:int = selectionState.anchorPosition;
			var activePosition:int = selectionState.activePosition;
			var endFlag:Boolean = selectionState.endFlag;
			var curPara:ParaElement;
			var curTxLine:TxLine;
			
			if(!extendSelection) // shift key is not pressed
			{
				if(anchorPosition != activePosition) // area selection
				{
					//todo
				}
				else // caret selection
				{
					if(endFlag == false)
					{
						curPara = dom.findParaAtPosition(anchorPosition);
						curTxLine = dom.composer.findTxLineAtPosition(anchorPosition);
						
						var lastOffset:int = curTxLine.paraBeginIndex + curTxLine.textLength -1;
						var lastCharCode:int = curPara.getCharCodeAtPosition(lastOffset);
						if(lastCharCode == 0x2028 || lastCharCode == 0x2029)
						{
							anchorPosition = activePosition = curPara.absoluteStart + lastOffset;
						}
						else 
						{
							anchorPosition = activePosition = curPara.absoluteStart + lastOffset + 1;
							endFlag = true;
						}
						
					}
				}
			}
			else 
			{
				//TODO: implement
			}
			
			isChanged = checkChange(selectionState, anchorPosition, activePosition, endFlag);
			
			if(isChanged)
				selectionState.updateRange(anchorPosition, activePosition, endFlag);
				
			return isChanged;
		}
		
		public static function startOfLine(selectionState:SelectionState, extendSelection:Boolean):Boolean
		{
			var isChanged:Boolean;
			var dom:DOMElement = selectionState.dom;
			var anchorPosition:int = selectionState.anchorPosition;
			var activePosition:int = selectionState.activePosition;
			var endFlag:Boolean = selectionState.endFlag;
			var curPara:ParaElement;
			var curTxLine:TxLine;
			var curTextLine:TextLine;
			var prevPara:ParaElement;
			var prevTxLine:TxLine;
			var prevTextLine:TextLine;
			
			if(!extendSelection) // shift key is not pressed
			{
				if(anchorPosition != activePosition) // area selection
				{
					//todo
				}
				else // caret selection
				{
					if(selectionState.endFlag)
					{
						prevPara = dom.findParaAtPosition(anchorPosition -1);
						prevTxLine = dom.composer.findTxLineAtPosition(anchorPosition -1);
						anchorPosition =  activePosition = prevPara.absoluteStart + prevTxLine.paraBeginIndex;
						endFlag = false;
					}
					else
					{
						curPara = dom.findParaAtPosition(anchorPosition);
						curTxLine = dom.composer.findTxLineAtPosition(anchorPosition);
						anchorPosition =  activePosition = curPara.absoluteStart + curTxLine.paraBeginIndex;
					}
				}
			}
			else 
			{
				//TODO: implement
			}
			
			isChanged = checkChange(selectionState, anchorPosition, activePosition, endFlag);
			
			if(isChanged)
				selectionState.updateRange(anchorPosition, activePosition, endFlag);
				
			return isChanged;
		}
		
		public static function previousLine(selectionState:SelectionState, extendSelection:Boolean):Boolean
		{
			var isChanged:Boolean;
			var dom:DOMElement = selectionState.dom;
			var anchorPosition:int = selectionState.anchorPosition;
			var activePosition:int = selectionState.activePosition;
			var endFlag:Boolean = selectionState.endFlag;
			var curPara:ParaElement;
			var curTxLine:TxLine;
			var curTextLine:TextLine;
			var prevPara:ParaElement;
			var prevTxLine:TxLine;
			var prevTextLine:TextLine;
			
			if(!extendSelection) // shift key is not pressed
			{
				if(anchorPosition != activePosition) // area selection
				{
					//todo
				}
				else // caret selection
				{
					if(selectionState.endFlag)
					{
						
					}
					else
					{
						
					}
				}
			}
			else 
			{
				//TODO: implement
			}
			
			isChanged = checkChange(selectionState, anchorPosition, activePosition, endFlag);
			
			if(isChanged)
				selectionState.updateRange(anchorPosition, activePosition, endFlag);
				
			return isChanged;
		}
		
		public static function nextLine(selectionState:SelectionState, extendSelection:Boolean):Boolean
		{
			return false; // not implemented yet
			var isChanged:Boolean;
			var dom:DOMElement = selectionState.dom;
			var anchorPosition:int = selectionState.anchorPosition;
			var activePosition:int = selectionState.activePosition;
			var endFlag:Boolean = selectionState.endFlag;
			var curPara:ParaElement;
			var curCursorPoint:Point;
			var curTxLine:TxLine;
			var curTextLine:TextLine;
			var nextPara:ParaElement;
			var nextTxLine:TxLine;
			var nextTextLine:TextLine;
			var nextLastCharCode:int;
			
			if(!extendSelection) // shift key is not pressed
			{
				if(anchorPosition != activePosition) // area selection
				{
					//todo
				}
				else // caret selection
				{
					
					
					if(selectionState.endFlag)
					{
						
					}
					else
					{
						curPara = dom.findParaAtPosition(anchorPosition);
						curTxLine = dom.composer.findTxLineAtPosition(anchorPosition);
						curTextLine = dom.composer.findLineAtPosition(anchorPosition);
						var curAtomIndex:int =  curTextLine.getAtomIndexAtCharIndex(anchorPosition - curPara.absoluteStart);
						var cursorLocalBound:Rectangle = curTextLine.getAtomBounds(curAtomIndex);
						curCursorPoint = curTextLine.localToGlobal(new Point(cursorLocalBound.x, cursorLocalBound.y));
						trace("curCursorPosition:"+curCursorPoint);
						var lastOffset:int = curTxLine.paraBeginIndex + curTxLine.textLength -1;
						var lastCharCode:int = curPara.getCharCodeAtPosition(lastOffset);
						
						if(curPara.absoluteStart + lastOffset +1 < dom.textLength )
						{
							nextPara = dom.findParaAtPosition(curPara.absoluteStart + lastOffset + 1);
							nextTxLine = dom.composer.findTxLineAtPosition(curPara.absoluteStart + lastOffset + 1);
							nextLastCharCode = nextPara.getCharCodeAtPosition(nextTxLine.paraBeginIndex + nextTxLine.textLength -1);
							
							for(var i:int=0; i<nextTxLine.segments.length; i++)
							{
								var segment:TxLineSegment = nextTxLine.segments.getItemAt(i) as TxLineSegment;
								nextTextLine = segment.textLine;
								
							}
							
							
							if(nextLastCharCode == 0x2028 || nextLastCharCode == 0x2029)
							{
								anchorPosition = activePosition = nextPara.absoluteStart + nextTxLine.paraBeginIndex + nextTxLine.textLength -1;
							}
							else 
							{
								anchorPosition = activePosition = nextPara.absoluteStart + nextTxLine.paraBeginIndex + nextTxLine.textLength;
								endFlag = true;
							}
						}
					}
				}
			}
			else 
			{
				//TODO: implement
			}
			
			isChanged = checkChange(selectionState, anchorPosition, activePosition, endFlag);
			
			if(isChanged)
				selectionState.updateRange(anchorPosition, activePosition, endFlag);
				
			return isChanged;
		}
		
		public static function checkChange(selectionState:SelectionState, anchorPosition:int, activePosition:int, endFlag:Boolean):Boolean
		{
			var isChanged:Boolean = false; 
			if(anchorPosition != selectionState.anchorPosition ||  activePosition != selectionState.activePosition || endFlag != selectionState.endFlag)
			{
				isChanged = true;
			}
			
			return isChanged
		}

	}
}